-- Para poder extraer los bits de signo, mantisa y exponente
with Ada.Unchecked_Conversion;
with Interfaces;

package IEEE754 is

  --***************************
  --* Tipos de datos publicos *
  --***************************

  -- Entero de 32 bits sin signo
  subtype TEnteroIEEE754 is Interfaces.Unsigned_32;

  -- Entero de 64 bits sin signo
  subtype TEnteroDobleIEEE754 is Interfaces.Unsigned_64;

  -- Indicamos el rango de valores y el numero de bits ('size) para cada tipo utilizado,
  -- para poder extraer los bits de forma correcta del entero de 32 bits.
  type TBitSigno is Mod 2**1;
  for TBitSigno'size use 1;

  type TExponente is Mod 2**8;
  for TExponente'size use 8;

  type TMantisa is Mod 2**23;
  for TMantisa'size use 23;

  -- Tipo de datos para representar signo, exponente y mantisa de un real
  -- en formato IEEE754
  type TFloatIEEE754 is
    record
      signo     : TBitSigno;
      exponente : TExponente;
      mantisa   : TMantisa;
    end record;

  -- Indicamos que bits del registro ocupa cada campo del mismo,
  -- ya que sino no podemos garantizar que dichos campos se almacenen en memoria
  -- en ese mismo orden.
  -- De esta forma podremos rellenar los bits de forma correcta a partir
  -- del entero de 32 bits (el tipo TEnteroIEEE754 declarado antes).
  for TFloatIEEE754 use
    record
      signo     at 0 range  31 .. 31;
      exponente at 0 range  23 .. 30;
      mantisa   at 0 range  0 .. 22;
      end record;

   INFINITO: constant TEnteroIEEE754 := 16#7F800000#;
   NAN: constant TEnteroIEEE754 := 16#7F800001#;
   MASCARA_SIGNO: constant TEnteroIEEE754 := 16#80000000#;
   MASCARA_EXPONENTE: constant TEnteroIEEE754 := 16#7F800000#;
   MASCARA_MANTISA_IEEE: constant TEnteroIEEE754 := 16#7FFFFF#;
   MASCARA_MANTISA_COMPLETA: constant TEnteroIEEE754 := 16#FFFFFF#;


  --***************************************
  --* Funciones y procedimientos publicos *
  --***************************************

  -- Conversion de Entero de 32 bits (en formato IEEE754) al tipo interno definido.
  -- Ada.Unchecked_Conversion convierte un tipo a otro bit a bit, sin realizar ninguna comprobacion.
  -- Si las variables no tiene el mismo numero de bits, el resultado dependera de la implementacion
  -- (mejor que esto no suceda: por eso utilizamos el atributo 'size).
   function aIEE754 is new Ada.Unchecked_Conversion (Source => TEnteroIEEE754, Target => TFloatIEEE754);

  -- Conversion inversa: del tipo TFloatIEEE754 a entero de 32 bits
   function aEntero is new Ada.Unchecked_Conversion (Source => TFloatIEEE754, Target => TEnteroIEEE754);

   -- Suma de numeros reales en formato IEEE754
   function sumaComaFlotante(sumando1 : TFloatIEEE754; sumando2 : TFloatIEEE754) return TFloatIEEE754;

   -- Suma de numeros reales en representacion de entero
   function sumaComaFlotante(sumando1 : Integer; sumando2 : Integer) return Integer;

   -- Resta de numeros reales en representacion de entero
   function restaComaFlotante(sumando1 : Integer; sumando2 : Integer) return Integer;

   -- Producto de numeros enteros sin signo
   function multiplicarSinSigno(op1: TEnteroIEEE754; op2: TEnteroIEEE754) return TEnteroDobleIEEE754;

   -- Producto de numeros reales en formato IEEE754
   function multiplicarComaFlotante(op1: TFloatIEEE754; op2: TFloatIEEE754) return TFloatIEEE754;

   -- Producto de numeros reales en representacion de entero
   function multiplicarComaFlotante(op1: Integer; op2: Integer) return Integer;

   -- Division de numeros reales en formato IEEE754
   function dividirComaFlotante(a: TFloatIEEE754; b: TFloatIEEE754) return TFloatIEEE754;

   -- Division de numeros reales en representacion de entero
   function dividirComaFlotante(a: Integer; b: Integer) return Integer;

end IEEE754;
